﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ClusterController.cs" company="DissingNellemann">
//   
// All rights reserved </copyright>
// <summary>
//   The cluster controller.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Website.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;

    using Website.CRUDServices;
    using Website.Models;
    using Website.Models.Styling;
    using Website.Models.ViewModels;

    using ClusterMethod = Website.Models.ViewModels.ClusterMethod;
    using File = Website.CRUDServices.File;

    /// <summary>
    ///     The cluster controller.
    /// </summary>
    public class ClusterController : BaseController
    {
        #region Public Methods and Operators

        /// <summary>
        ///     The get header items.
        /// </summary>
        /// <returns>
        ///     The list of headeritems for a cluster view.
        /// </returns>
        public static List<TableViewHeaderItem> GetHeaderItems()
        {
            var headerItems = new List<TableViewHeaderItem>();
            var item1 = new TableViewHeaderItem { Text = "Dato", SortableName = "TimeOfActivity", IsSortable = true, };

            var item2 = new TableViewHeaderItem { Text = "Lokation", SortableName = "Location.Name", IsSortable = true };
            var item3 = new TableViewHeaderItem { Text = "Navn", SortableName = "Name", IsSortable = true };
            var item4 = new TableViewHeaderItem { Text = "Metoder", SortableName = string.Empty, IsSortable = false };
            var item5 = new TableViewHeaderItem
                            {
                                Text = "Sidste Status",
                                SortableName = string.Empty,
                                IsSortable = false
                            };
            headerItems.Add(item1);
            headerItems.Add(item2);
            headerItems.Add(item3);
            headerItems.Add(item4);
            headerItems.Add(item5);

            return headerItems;
        }

        /// <summary>
        /// The index.
        /// </summary>
        /// <param name="skip">
        /// The skip.
        /// </param>
        /// <param name="take">
        /// The take.
        /// </param>
        /// <param name="orderBy">
        /// The order by.
        /// </param>
        /// <param name="sortAscending">
        /// The sort ascending.
        /// </param>
        /// <returns>
        /// The <see cref="ActionResult"/>.
        /// </returns>
        public ActionResult Index(int? skip, int? take, string orderBy, bool? sortAscending)
        {
            this.Session["CurrentSubMenuSelection"] = "Clusters";

            ListView<Cluster> view = null;

            List<TableViewHeaderItem> headerItems = GetHeaderItems();

            CRUDServiceProvider.WithCRUDService(
                client =>
                {
                    var query = new ClusterQuery
                                    {
                                        Settings =
                                            new SearchSettings
                                                {
                                                    SortAscending = sortAscending ?? false,
                                                    Skip = skip ?? 0,
                                                    Take = take ?? 20,
                                                    OrderBy =
                                                        !string.IsNullOrEmpty(orderBy)
                                                            ? orderBy
                                                            : "TimeOfActivity"
                                                }
                                    };

                    IResult iRes = client.Query(query);
                    if (iRes != null)
                    {
                        var res = (ClusterResult)iRes;
                        view = new ListView<Cluster>(
                            res.List.ToList(),
                            skip ?? 0,
                            take ?? 20,
                            res.TotalRowCount,
                            query.Settings.OrderBy,
                            sortAscending ?? false,
                            headerItems,
                            "Index");

                        var uniqueClusterMethods = new List<Guid>();
                        foreach (var methods in res.List.Select(x => x.Methods))
                        {
                            uniqueClusterMethods.AddRange(methods.ToList());
                        }

                        var uniqueClusterStatuses = new List<Guid>();
                        foreach (var statuses in res.List.Select(x => x.Statuses))
                        {
                            uniqueClusterStatuses.AddRange(statuses.ToList());
                        }

                        this.ViewData["ClusterMethods"] =
                            PrimitiveTypes.GetClusterMethodsWithIDs(uniqueClusterMethods.Distinct());
                        this.ViewData["ClusterStatuses"] =
                            PrimitiveTypes.GetClusterStatusWithIDs(uniqueClusterStatuses.Distinct());
                        this.ViewData["ClusterMethodTypes"] = PrimitiveTypes.GetClusterMethodType();
                        this.ViewData["ClusterStatusTypes"] = PrimitiveTypes.GetClusterStatusType();
                    }
                });

            this.ViewData["Locations"] = PrimitiveTypes.GetLocations();

            return View(view);
        }

        /// <summary>
        ///     The new cluster.
        /// </summary>
        /// <returns>
        ///     The <see cref="ActionResult" />.
        /// </returns>
        public ActionResult NewCluster()
        {
            this.ViewData["CreateLocationActionName"] = "CreateLocationJson";
            this.ViewData["Regions"] = PrimitiveTypes.GetRegions();
            this.ViewData["Locations"] = PrimitiveTypes.GetLocations();
            this.ViewData["Profiles"] = PrimitiveTypes.GetProfiles();
            this.ViewData["ClusterStatusTypes"] = PrimitiveTypes.GetClusterStatusType();
            this.ViewData["ClusterMethodTypes"] = PrimitiveTypes.GetClusterMethodType();
            this.ViewData["Projects"] = PrimitiveTypes.GetProjects();
            return this.View();
        }

        /// <summary>
        /// The new cluster.
        /// </summary>
        /// <param name="clusterStatus">
        /// The cluster status.
        /// </param>
        /// <param name="cluster">
        /// The cluster.
        /// </param>
        /// <param name="ownerProjects">
        /// The owner projects.
        /// </param>
        /// <param name="clusterMethod">
        /// The cluster method.
        /// </param>
        /// <returns>
        /// The <see cref="ActionResult"/>.
        /// </returns>
        [HttpPost]
        public ActionResult NewCluster(
            IList<Models.ViewModels.ClusterStatus> clusterStatus,
            Cluster cluster,
            List<Guid> ownerProjects,
            IList<ClusterMethod> clusterMethod)
        {
            CRUDServiceProvider.WithCRUDService(
                client =>
                {
                    var methods = new List<CRUDServices.ClusterMethod>();

                    //added check for whether it's checked or not
                    foreach (ClusterMethod clust in clusterMethod.Where(x => x.Checked))
                    {
                        var met = new CRUDServices.ClusterMethod
                                      {
                                          ID = Guid.NewGuid(),
                                          Comments = clust.Comments,
                                          ArchiveLocation = clust.ArchiveLocation,
                                          Type = clust.Type
                                      };

                        // check for files
                        if (clust.PostedFiles != null)
                        {
                            var crudFiles = new List<Guid>();
                            foreach (HttpPostedFileBase file in clust.PostedFiles)
                            {
                                if (file != null)
                                {
                                    var dtoFile = new File
                                                      {
                                                          ID = Guid.NewGuid(),
                                                          ContentType = file.ContentType,
                                                          Name =
                                                              file.FileName.Contains('\\')
                                                                  ? file.FileName.Substring(
                                                                      file.FileName.LastIndexOf('\\') + 1)
                                                                  : file.FileName
                                                      };

                                    using (var memstream = new MemoryStream())
                                    {
                                        file.InputStream.CopyTo(memstream);
                                        dtoFile.ContentData = memstream.ToArray();
                                    }

                                    crudFiles.Add(dtoFile.ID);

                                    var cfm = new CreateFileCommand { NewFile = dtoFile };
                                    client.ExecuteCommand(cfm);
                                }
                            }

                            met.Files = crudFiles.ToArray();
                        }

                        // add to list
                        methods.Add(met);

                        // save it
                        var cmd = new CreateClusterMethodCommand { Method = met };
                        client.ExecuteCommand(cmd);
                    }

                    var statuses = new List<CRUDServices.ClusterStatus>();
                    foreach (Models.ViewModels.ClusterStatus cs in clusterStatus.Where(x => x.Checked))
                    {
                        var status = new CRUDServices.ClusterStatus()
                        {
                            ID = Guid.NewGuid(),
                            IsActive = cs.IsActive,
                            Type = cs.Type,
                            Comments = cs.Comments,
                        };

                        // add to list
                        statuses.Add(status);

                        // save it
                        var cmd = new CreateClusterStatusCommand { Status = status };
                        client.ExecuteCommand(cmd);
                    }

                    cluster.Methods = (from m in methods select m.ID).ToArray();
                    cluster.Statuses = (from m in statuses select m.ID).ToArray();
                    cluster.ID = Guid.NewGuid();
                    cluster.OwnerProjects = (ownerProjects ?? new List<Guid>()).ToArray();

                    // save the final cluster product
                    var ccmd = new CreateClusterCommand { Cluster = cluster };
                    client.ExecuteCommand(ccmd);
                });

            return this.RedirectToAction("Index");
        }

        public ActionResult UpdateCluster(Guid id)
        {
            this.ViewData["CreateLocationActionName"] = "CreateLocationJson";
            this.ViewData["Regions"] = PrimitiveTypes.GetRegions();
            this.ViewData["Locations"] = PrimitiveTypes.GetLocations();
            this.ViewData["Profiles"] = PrimitiveTypes.GetProfiles();
            this.ViewData["ClusterStatusTypes"] = PrimitiveTypes.GetClusterStatusType();
            this.ViewData["ClusterMethodTypes"] = PrimitiveTypes.GetClusterMethodType();
            this.ViewData["Projects"] = PrimitiveTypes.GetProjects();

            // load object for editing
            var clust = new Cluster();
            CRUDServiceProvider.WithCRUDService(
                client =>
                {
                    //get the Cluster object
                    var query = new ClusterQuery { Settings = new SearchSettings { IDEquals = id } };
                    var res = client.Query(query) as ClusterResult;
                    if (res != null)
                    {
                        if (res.List.Any())
                        {
                            clust = res.List[0];
                        }
                    }
                    if (clust != null)
                    {
                        //get the clsutermethods
                        List<CRUDServices.ClusterMethod> methods = new List<CRUDServices.ClusterMethod>();

                        var methodquery = new ClusterMethodQuery { Settings = new SearchSettings { IDIsIn = clust.Methods } };
                        var methodres = client.Query(methodquery) as ClusterMethodResult;
                        if (methodres != null)
                        {
                            if (methodres.List.Any())
                            {
                                methods.AddRange(methodres.List);
                            }
                        }
                        this.ViewData["ClusterMethods"] = methods;
                        //get the clusterstatuses
                        List<CRUDServices.ClusterStatus> statuses = new List<CRUDServices.ClusterStatus>();

                        var statusquery = new ClusterStatusQuery { Settings = new SearchSettings { IDIsIn = clust.Statuses } };
                        var statusres = client.Query(statusquery) as ClusterStatusResult;
                        if (statusres != null)
                        {
                            if (statusres.List.Any())
                            {
                                statuses.AddRange(statusres.List);
                            }
                        }
                        this.ViewData["ClusterStatuses"] = statuses;
                    }
                });


            // ensure we have some content
            if (clust != null)
            {
                return View(clust);
            }
            // something buggered up. Better send them back to the index.
            return this.RedirectToAction("Index");
        }

        [HttpPost]
        public ActionResult UpdateCluster(
            IList<Models.ViewModels.ClusterStatus> clusterStatus,
            Cluster cluster,
            List<Guid> ownerProjects,
            IList<ClusterMethod> clusterMethod)
        {
            CRUDServiceProvider.WithCRUDService(
                client =>
                {
                    var methods = new List<CRUDServices.ClusterMethod>();

                    //added check for whether it's checked or not
                    foreach (ClusterMethod clust in clusterMethod.Where(x => x.Checked))
                    {
                        var met = new CRUDServices.ClusterMethod
                        {
                            ID = clust.ID,
                            Comments = clust.Comments,
                            ArchiveLocation = clust.ArchiveLocation,
                            Type = clust.Type
                        };

                        // check for files
                        if (clust.PostedFiles != null)
                        {
                            var crudFiles = new List<Guid>();
                            foreach (HttpPostedFileBase file in clust.PostedFiles)
                            {
                                if (file != null)
                                {
                                    var dtoFile = new File
                                    {
                                        ID = Guid.NewGuid(),
                                        ContentType = file.ContentType,
                                        Name =
                                            file.FileName.Contains('\\')
                                                ? file.FileName.Substring(
                                                    file.FileName.LastIndexOf('\\') + 1)
                                                : file.FileName
                                    };

                                    using (var memstream = new MemoryStream())
                                    {
                                        file.InputStream.CopyTo(memstream);
                                        dtoFile.ContentData = memstream.ToArray();
                                    }

                                    crudFiles.Add(dtoFile.ID);

                                    var cfm = new CreateFileCommand { NewFile = dtoFile };
                                    client.ExecuteCommand(cfm);
                                }
                            }

                            met.Files = crudFiles.ToArray();
                        }

                        // add to list
                        methods.Add(met);

                        // save it
                        var cmd = new CreateClusterMethodCommand { Method = met };
                        client.ExecuteCommand(cmd);
                    }

                    var statuses = new List<CRUDServices.ClusterStatus>();
                    foreach (Models.ViewModels.ClusterStatus cs in clusterStatus.Where(x => x.Checked))
                    {
                        var status = new CRUDServices.ClusterStatus()
                        {
                            ID = cs.ID,
                            IsActive = cs.IsActive,
                            Type = cs.Type,
                            Comments = cs.Comments,
                        };

                        // add to list
                        statuses.Add(status);

                        // save it
                        var cmd = new CreateClusterStatusCommand { Status = status };
                        client.ExecuteCommand(cmd);
                    }

                    cluster.Methods = (from m in methods select m.ID).ToArray();
                    cluster.Statuses = (from m in statuses select m.ID).ToArray();
                    cluster.OwnerProjects = (ownerProjects ?? new List<Guid>()).ToArray();

                    // save the final cluster product
                    var ccmd = new CreateClusterCommand { Cluster = cluster };
                    client.ExecuteCommand(ccmd);
                });

            return this.RedirectToAction("Index");
        }

        #endregion
    }
}